﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CdcSoftware.Pivotal.Applications.Core.Server;
using CdcSoftware.Pivotal.Applications.Core.Common;
using System.Data;
using CdcSoftware.Pivotal.Engine.Types.DataTemplates;
using CdcSoftware.Pivotal.Engine;
using CdcSoftware.Pivotal.Engine.Types.ServerTasks;
using CdcSoftware.Pivotal.Engine.Mail;
using System.Text.RegularExpressions;
using CdcSoftware.Pivotal.Engine.Types.Reports;
using CdcSoftware.Pivotal.Engine.DataServices;
using CdcSoftware.Pivotal.Engine.Types.Database;
using Pcm.Retail.Server.FormTasks.AppleCare;
using System.IO;
using System.Xml;

namespace Pcm.Retail.Server.FormTasks
{
    public class RESales : AbstractDataTemplateServerTask
    {
        //AS 20-06-2013: Static Memory varaibles added to store data from AppleCare Authenticate Webservice call.
        public static string m_appleCareUserSessionId = string.Empty;
        public static string m_appleCareUserOperationId = string.Empty;

        //AS 20-06-2013: Static Memory varaibles added to store the Datetime value when the AppleCare Authenticate Webservice is called.
        //With Authenticate call we get the session for 30 minutes.
        //Therfore we need to fetch another session before thsi session expiers.
        //This memory varaible will store the value when the Session was started.
        public static DateTime AppleCareSessionDateTime = DateTime.MinValue;

        public RESales()
        {
            this.DefaultResourceBundleName = "RE_Email";            
        }

        #region Apple Care Properties

        /// <summary>
        /// Will call the AppleCareAuthenticate() function.
        /// This fucntion will check if there is already a active session(difference between sessionStartDateTime and currentDateTime is less than 25 minutes) then 
        /// will return the alreday stored m_appleCareUserSessionId 
        /// ELSE will call the Apple Care Authenticate webservice and fetch another session details.
        /// </summary>
        public string AppleCareUserSessionId
        {
            get
            {
                AppleCareAuthenticate();
                return m_appleCareUserSessionId;
            }
        }

        /// <summary>
        /// Will call the AppleCareAuthenticate() function.
        /// This fucntion will check if there is already a active session(difference between sessionStartDateTime and currentDateTime is less than 25 minutes) then 
        /// will return the alreday stored m_appleCareUserOperationId 
        /// ELSE will call the Apple Care Authenticate webservice and fetch another session details.
        /// </summary>
        public string AppleCareOperationId
        {
            get
            {
                AppleCareAuthenticate();
                return m_appleCareUserOperationId;
            }
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataTemplate"></param>
        /// <param name="data"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        protected override Id AddData(DataTemplate dataTemplate, DataSet data, ParameterList parameters)
        {
            //Set the Receipt number and auto increment.
            data.Tables[0].Rows[0]["RE_Receipt_Number"] = GetNewReceiptNumber(data.Tables[0].Rows[0]["RE_Store_Id"]);

            return base.AddData(dataTemplate, data, parameters);
        }

        /// <summary>
        /// Save record.
        /// </summary>
        /// <param name="dataTemplate"></param>
        /// <param name="data"></param>
        /// <param name="parameters"></param>
        protected override void SaveData(DataTemplate dataTemplate, DataSet data, ParameterList parameters)
        {
            try
            {
                DataRow primaryRow = data.Tables[0].Rows[0];
                if (TypeConvert.ToString(primaryRow["RE_Type"]) == "Deposit" && Convert.IsDBNull(primaryRow["RE_Deposit_Status"]))
                    primaryRow["RE_Deposit_Status"] = "Pending";

                base.SaveData(dataTemplate, data, parameters);

                //DS: No Membership/Staff quota as of now.
                //DataRow primaryRow = data.Tables[0].Rows[0];
                //DataTable orderProducts = data.Tables["SFA_Order__Product_SFA_Order_I"];

                //this.UpdateQuotaForVIPMemberOrStaff(primaryRow, orderProducts);

                //For Conversion of Deposit to Sale, update the Deposit order to either Pending or Processed.
                if (string.Equals(TypeConvert.ToString(primaryRow["RE_Order_Status"]), "Processed") && !Convert.IsDBNull(primaryRow["RE_Sale_Deposit_Link_Id"]))
                {
                    DataRow depositOrder = DefaultDataAccess.GetDataRow("SFA_Order", Id.Create(primaryRow["RE_Sale_Deposit_Link_Id"]), "RE_Deposit_Status", "RE_Type");
                    if (depositOrder != null && TypeConvert.ToString(depositOrder["RE_Type"]) == "Deposit" && TypeConvert.ToString(depositOrder["RE_Deposit_Status"]) == "Pending")
                    {
                        depositOrder["RE_Deposit_Status"] = "Processed";
                        DefaultDataAccess.SaveDataRow(depositOrder);
                    }
                }
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }       

        /// <summary>
        /// Method overridden to support the default setting of the default fields passed through transition point param.
        /// </summary>
        /// <param name="dataTemplate"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    25-02-2011      DS          Initial version for Retail.
        /// </history>
        protected override DataSet NewData(DataTemplate dataTemplate, ParameterList parameters)
        {
            try
            {
                this.TransitionPointParameter.ParameterList = parameters;
                DataSet dataSet = this.SystemServer.DataService.NewDataDirect(dataTemplate, parameters);
                DataRow primaryDataRow = dataSet.Tables[dataTemplate.PrimaryDataSection.Name].Rows[0];
                this.TransitionPointParameter.SetDefaultColumns(primaryDataRow);
                this.TransitionPointParameter.CopyToParameterList(parameters);
                return dataSet;
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Update the Vouchers as either Sold/Redeemed.
        /// </summary>
        /// <param name="orderDataSet"></param>
        [TaskExecute]
        public void UpdateVouchers(DataSet orderDataSet)
        {
            try
            {
                //Revert any Voucher Sold to In Stock.
                DataRow primaryDataRow = orderDataSet.Tables[0].Rows[0];
                if (TypeConvert.ToString(primaryDataRow["RE_Order_Status"]).ToUpper() == "VOID")
                {
                    //Revert any Voucher Redeemed to Sold.
                    DataTable orderTenders = orderDataSet.Tables["RE_Order_Tender_Order_Id"];
                    DataRow[] serializedVoucherRows = orderTenders.AsEnumerable().Where(a => TypeConvert.ToBoolean(a["Voucher"])
                        && TypeConvert.ToBoolean(a["Tender_Type_Id__Default_"]) && !Convert.IsDBNull(a["Product_Serial_No_Id"])).ToArray();
                    foreach (DataRow dr in serializedVoucherRows)
                    {
                        DataRow voucherRow = DefaultDataAccess.GetDataRow("RE_Product_Serial_No", Id.Create(dr["Product_Serial_No_Id"]), "Voucher_Status");
                        if (voucherRow != null && String.Equals(TypeConvert.ToString(voucherRow["Voucher_Status"]), "Redeemed"))
                        {
                            voucherRow["Voucher_Status"] = "Sold";
                            DefaultDataAccess.SaveDataRow(voucherRow);
                        }
                    }
                }
                else if (TypeConvert.ToString(primaryDataRow["RE_Order_Status"]).ToUpper() == "PROCESSED")
                {
                    //This scenario is handled in Inventory.
                    ////Post sale, update the Voucher status to Sold and Expiry date to date based on the days defined in LOB..
                    //DataTable orderProducts = orderDataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                    //DataRow[] serializedVoucherRowsForSale = orderProducts.AsEnumerable().Where(a => TypeConvert.ToBoolean(a["RE_Product_Serial_No_Id__Vouch"])
                    //    && !Convert.IsDBNull(a["RE_Product_Serial_No_Id"])).ToArray();
                    //foreach (DataRow dr in serializedVoucherRowsForSale)
                    //{
                    //    DataRow voucherRow = DefaultDataAccess.GetDataRow("RE_Product_Serial_No", Id.Create(dr["RE_Product_Serial_No_Id"]), "Voucher_Status",
                    //        "Voucher_Expiry_Date");
                    //    if (voucherRow != null && String.Equals(TypeConvert.ToString(voucherRow["Voucher_Status"]), "In Stock"))
                    //    {
                    //        voucherRow["Voucher_Status"] = "Sold";
                    //        voucherRow["Voucher_Expiry_Date"] = DateTime.Today.AddMonths(TypeConvert.ToInt16(primaryDataRow["RE_LOB_Id__Voucher_Expiry_In_M"]));
                    //        DefaultDataAccess.SaveDataRow(voucherRow);
                    //    }
                    //}

                    //Where Default is true, then update the vouchers to be redeemed in the RE_Product_Voucher_Serial table.
                    DataTable orderTenders = orderDataSet.Tables["RE_Order_Tender_Order_Id"];
                    DataRow[] serializedVoucherRows = orderTenders.AsEnumerable().Where(a => TypeConvert.ToBoolean(a["Voucher"])
                        && TypeConvert.ToBoolean(a["Tender_Type_Id__Default_"]) && !Convert.IsDBNull(a["Product_Serial_No_Id"])).ToArray();
                    foreach (DataRow dr in serializedVoucherRows)
                    {
                        DataRow voucherRow = DefaultDataAccess.GetDataRow("RE_Product_Serial_No", Id.Create(dr["Product_Serial_No_Id"]), "Voucher_Status");
                        if (voucherRow != null && String.Equals(TypeConvert.ToString(voucherRow["Voucher_Status"]), "Sold"))
                        {
                            voucherRow["Voucher_Status"] = "Redeemed";
                            DefaultDataAccess.SaveDataRow(voucherRow);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Added DeleteData to implement CascadeDelete for SFA_Order table.
        /// Since we are inheriting from "AbstractDataTemplateServerTask" call to base.DeleteData will perform the Cascade Delete depending on the "Delete Action"
        /// specified on Table-Fields.
        /// </summary>
        /// <param name="dataTemplate"></param>
        /// <param name="rowId"></param>
        /// <param name="parameters"></param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>        
        protected override void DeleteData(DataTemplate dataTemplate, Id rowId, ParameterList parameters)
        {
            try
            {
                //Used to Cascade Delete "RE_Authirization","SFA__Order_Product" table.
                base.DeleteData(dataTemplate, rowId, parameters);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message,exc);
            }
        }

        /// <summary>
        /// Incrementing Receipt Number with each new form load.
        /// </summary>
        /// <param name="dStore">Datatable from Client</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        public virtual void DeleteSalesAndDependentRecords(DataTemplate dataTemplate,Id recordId)
        {
            try
            {
                this.DeleteData(dataTemplate, recordId, null);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }
        
        /// <summary>
        /// The sale which converts the customer to VIP member also should be included as the first sale for the VIP member.
        /// </summary>
        /// <param name="contactId">Contact to update</param>
        /// <param name="lastPurchaseAmount">Last Purchase Amount</param>
        /// <param name="lastPurchaseOn">Last Purchase Date</param>
        /// <param name="discount">Discount amount given in the current sale.</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        protected virtual void UpdateContactForVIPMemberSale(object contactId, object lastPurchaseAmount, object discount)
        {
            try
            {
                DataRow contact = this.DefaultDataAccess.GetDataRow("Contact", Id.Create(contactId), "RE_Last_Purchase_Amount", "RE_Last_Purchase_On",
                    "RE_Amount_Spent_Till_Date", "RE_Discount_Given_Till_Date");

                contact["RE_Last_Purchase_Amount"] = lastPurchaseAmount;
                contact["RE_Last_Purchase_On"] = DateTime.Now.Date;
                contact["RE_Amount_Spent_Till_Date"] = TypeConvert.ToDouble(contact["RE_Amount_Spent_Till_Date"]) + TypeConvert.ToDouble(lastPurchaseAmount);
                contact["RE_Discount_Given_Till_Date"] = TypeConvert.ToDouble(contact["RE_Discount_Given_Till_Date"]) + TypeConvert.ToDouble(discount);
                this.DefaultDataAccess.SaveDataRow(contact);
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// On process sale, upsert the RE_Member_Bday_Disc_Quota for the contact and year with the correct value for used.
        /// ( sum of quantity for rows where the b'day discount is used)
        /// </summary>
        /// <param name="contactId"></param>
        /// <param name="quantityWithBdayDisc"></param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        protected virtual void MemberBdayDiscQuotaUsed(object contactId, int quantityWithBdayDisc)
        {
            try
            {
                DataTable memberBdayDiscQuota = this.DefaultDataAccess.GetDataTable("RE_Member Birthday Discount with Member ? Year ?", 
                    new object[]{ contactId, DateTime.Now.Year} , "Used");

                if (memberBdayDiscQuota != null && memberBdayDiscQuota.Rows.Count > 0)
                {
                    memberBdayDiscQuota.Rows[0]["Used"] = TypeConvert.ToInt32(memberBdayDiscQuota.Rows[0]["Used"]) + quantityWithBdayDisc;
                    this.DefaultDataAccess.SaveDataTable(memberBdayDiscQuota);
                }
                else
                {
                    DataRow memberBdayDiscQuotaRow = this.DefaultDataAccess.GetNewDataRow("RE_Member_Bday_Disc_Quota", "Contact_Id", "Year_", "Used");
                    memberBdayDiscQuotaRow["Contact_Id"] = contactId;
                    memberBdayDiscQuotaRow["Year_"] = DateTime.Now.Year;
                    memberBdayDiscQuotaRow["Used"] = quantityWithBdayDisc;
                    this.DefaultDataAccess.SaveDataRow(memberBdayDiscQuotaRow);
                }
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Updating the RE_Staff_Purchase record for each discount condition for the staff with the quantity in the corrsponding 
        /// row for the current year against the current month qty field on process sale.
        /// </summary>
        /// <param name="discount">Discount amount given in the current sale.</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        protected virtual void UpdateStaffPurchase(object orderId, object staffId)
        {
            try
            {
                DataTable staffPurchase = null;
                DataTable orderProduct = null;
               
                if (orderId == null)
                    return;

                orderProduct = this.DefaultDataAccess.GetDataTable("RE_Order Products with Order ?", new object[] { orderId }, "RE_Discount_Condition1_Id", "RE_Discount_Condition2_Id", "RE_Staff_Id", "Quantity");
                
                if (orderProduct.AsEnumerable().Count() > 0)
                {
                    foreach (DataRow oProd in orderProduct.Rows)
                    {
                        //Update the RE_Staff_Purchase record with Discount Condition, Staff_Id, Current Year and Month specific Quantities
                        //Could be multiple staff with there specific staff codes
                        //staffPurchase = this.DefaultDataAccess.GetDataTable("RE_Staff Purchase with Staff ?  Discount Condition ? Year ?", new object[] {oProd["RE_Staff_Id"], oProd["RE_Discount_Condition1_Id"], DateTime.Now.Year }, DateTime.Now.ToString("MMM") + "_Qty");
                        staffPurchase = this.DefaultDataAccess.GetDataTable("RE_Staff Purchase with Staff ?  Discount Condition ? Year ?", new object[] { staffId, oProd["RE_Discount_Condition1_Id"], DateTime.Now.Year }, DateTime.Now.ToString("MMM") + "_Qty");

                        //Each Staff will have one record for one current year
                        if (staffPurchase != null && staffPurchase.Rows.Count == 1)
                            staffPurchase.Rows[0][DateTime.Now.ToString("MMM") + "_Qty"] = TypeConvert.ToInt32(staffPurchase.Rows[0][DateTime.Now.ToString("MMM") + "_Qty"]) + TypeConvert.ToInt32(oProd["Quantity"]);
                        
                        this.DefaultDataAccess.SaveDataTable(staffPurchase);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Update logged-in row in the secondary for cashier login:
        ///•	For Cashier, End_Time = Current Time
        ///•    For the POS, Cashier_Id = null
        /// </summary>
        /// <param name="storeId">POS, to which the staff is logged in.</param>
        /// <history>
        /// Revision#      Date            Author          Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.                                              
        /// </history>
        [TaskExecute]
        public virtual void CashierAutoLogout(object posId)
        {
            try
            {
                DataTable cashierLogins = this.DefaultDataAccess.GetDataTable("RE_All Cashier Logins for Today where EndTime is Null with POS ?", 
                    new object[] { posId }, "End_Time");
                if (cashierLogins != null && cashierLogins.Rows.Count > 0)
                {
                    foreach (DataRow dr in cashierLogins.Rows)
                    {
                        dr["End_Time"] = DateTime.Now;
                    }
                }
                this.DefaultDataAccess.SaveDataTable(cashierLogins);

                DataRow posRow = this.DefaultDataAccess.GetDataRow("RE_Store_POS", Id.Create(posId), "Cashier_Id");

                if (posRow != null)
                {
                    posRow["Cashier_Id"] = DBNull.Value;
                }
                this.DefaultDataAccess.SaveDataRow(posRow);
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Send an notification mail to top management staff for the purchase.
        /// </summary>
        /// <param name="orderId">Order Id of the current sale.</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        protected virtual void SendTopManagementEmail(object orderId, string topMgmtEmail, string topMgmtName)
        {
            try
            {
                DataTable orderProduct = this.DefaultDataAccess.GetDataTable("RE_Order Products with OrderId?", new object[] { orderId }, new string[] { });
                DataTable authorization = this.DefaultDataAccess.GetDataTable("RE_Authorized by Staff for Order ?", new object[] { orderId }, "First_Name", "Last_Name");
                if (orderProduct != null && orderProduct.Rows.Count > 0)
                {
                    //Get the mail id for the Top Management.
                    StringBuilder mailBody = new StringBuilder();
                    mailBody.Append("Hi " + topMgmtName + "," + Environment.NewLine);
                    mailBody.Append(Environment.NewLine);
                    mailBody.Append("Following are the details of the recent purchase made:" + Environment.NewLine);
                    mailBody.Append("---------------------------------------" + Environment.NewLine);
                    mailBody.Append("Store  : " + orderProduct.Rows[0]["Store_Name"] + Environment.NewLine);
                    mailBody.Append("Address: " + orderProduct.Rows[0]["Receipt_Address"] + Environment.NewLine);
                    mailBody.Append("---------------------------------------" + Environment.NewLine);
                    mailBody.Append("Receipt No: " + orderProduct.Rows[0]["RE_Receipt_Number"] + Environment.NewLine);
                    mailBody.Append("Date/Time : " + orderProduct.Rows[0]["RE_Order_Date"] + Environment.NewLine);
                    mailBody.Append("Cashier   : " + orderProduct.Rows[0]["Staff_First_Name"] + Environment.NewLine);
                    mailBody.Append("---------------------------------------" + Environment.NewLine);
                    mailBody.Append("---------------------------------------" + Environment.NewLine);
                    //Print each item details.
                    foreach (DataRow dr in orderProduct.Rows)
                    {
                        mailBody.Append("Article  : " + dr["RE_Article_Number"] + Environment.NewLine);
                        mailBody.Append("Color    : " + dr["Color_Description"] + Environment.NewLine);
                        mailBody.Append("Item     : " + dr["Item_Description"] + Environment.NewLine);
                        mailBody.Append("Size     : " + dr["Size_Description"] + Environment.NewLine);
                        mailBody.Append("Quantity : " + dr["Quantity"] + Environment.NewLine);
                        mailBody.Append("Net Price: $" + dr["RE_Extended_Price"] + Environment.NewLine);
                        
                        if (!Convert.IsDBNull(dr["Disct_Condition1_ConditionID"]))
                        {
                            if (String.Equals(TypeConvert.ToString(dr["Disct_Condition1_Value_Type"]), "Percent"))
                            {
                                mailBody.Append("Discount Desc.: " + dr["Disct_Condition1_Description"] + Environment.NewLine);
                                mailBody.Append("Discount %    : " + dr["Disct_Condition1_Percent_Value"] + "%" + Environment.NewLine);
                                mailBody.Append("Total Discount: $" + dr["Tier1_Discount_Value"] + Environment.NewLine);
                            }
                            else
                            {
                                mailBody.Append("Discount Desc.: " + dr["Disct_Condition1_Description"] + Environment.NewLine);
                                mailBody.Append("Discount $    : $" + dr["Disct_Condition1_Amount"] + Environment.NewLine);
                                mailBody.Append("Total Discount: $" + dr["Tier1_Discount_Value"] + Environment.NewLine);
                            }
                        }
                        if(!Convert.IsDBNull(dr["Disct_Condition2_ConditionID"]))
                        {
                            if (String.Equals(TypeConvert.ToString(dr["Disct_Condition2_Value_Type"]), "Percent"))
                            {
                                mailBody.Append("Discount Desc.: " + dr["Disct_Condition2_Description"] + Environment.NewLine);
                                mailBody.Append("Discount %    : " + dr["Disct_Condition2_Percent_Value"] + "%" + Environment.NewLine);
                                mailBody.Append("Total Discount: $" + dr["Tier2_Discount_Value"] + Environment.NewLine);
                            }
                            else
                            {
                                mailBody.Append("Discount Desc.: " + dr["Disct_Condition2_Description"] + Environment.NewLine);
                                mailBody.Append("Discount $    : $" + dr["Disct_Condition2_Amount"] + Environment.NewLine);
                                mailBody.Append("Total Discount: $" + dr["Tier2_Discount_Value"] + Environment.NewLine);
                            }
                        }
                        mailBody.Append("---------------------------------------" + Environment.NewLine);
                    }
                    mailBody.Append("---------------------------------------" + Environment.NewLine);
                    mailBody.Append("Total Quantity: " + orderProduct.Rows[0]["RE_Total_Qty"] + Environment.NewLine);
                    mailBody.Append("Total Price   : $" + orderProduct.Rows[0]["Quote_Total"] + Environment.NewLine);
                    mailBody.Append(Environment.NewLine);
                    if (authorization != null && authorization.Rows.Count > 0)
                    {
                        mailBody.Append("Authorized By : " + TypeConvert.ToString(authorization.Rows[authorization.Rows.Count - 1]["First_Name"]) + " " +
                            TypeConvert.ToString(authorization.Rows[authorization.Rows.Count - 1]["Last_Name"]) + Environment.NewLine);
                        mailBody.Append(Environment.NewLine);
                    }
                    mailBody.Append("Thanks,");
                    mailBody.Append(Environment.NewLine);
                    mailBody.Append("Charles and Keith");
                    //Get the In-Charge who authorized the transaction (Authorization records).

                    //Create a new Email message with the generated report as an attachment.
                    EmailMessage emailMessage = this.SystemServer.CreateMessage();
                    emailMessage.To.Add(topMgmtEmail);
                    emailMessage.Subject = "Top Management Purchase: " + DateTime.Now;
                    emailMessage.IsBodyHtml = false;
                    emailMessage.Body = mailBody.ToString();
                    emailMessage.Send();
                }
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// This function is used to revert the quota in case the transaction is set to "VOID".
        /// This will be done for Customer Type as VIP Member or Staff.
        /// </summary>
        /// <param name="orderId">Order Id of the current sale.</param>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        private void UpdateQuotaForVIPMemberOrStaff(DataRow primaryDataRow,DataTable orderProducts)
        {
            try
            {
                int totalDiscountQty = 0;
                //Checking for VIP Members
                if (TypeConvert.ToString(primaryDataRow["RE_Order_Status"]).ToUpper() == "VOID" &&
                TypeConvert.ToString(primaryDataRow["RE_Customer_Type"]).ToUpper() == "MEMBER" &&
                TypeConvert.ToBoolean(primaryDataRow["Birthday_Promotion"]))
                {
                    //Fetching the discountId
                    Id memberBdayDiscountId = Id.Create(this.DefaultDataAccess.SqlIndex("RE_Loyalty_Program_Tier", "Member_Bday_Discount_Id", Id.Create(primaryDataRow["RE_Tier_Id"])));

                    if(memberBdayDiscountId != null)
                    {
                        var result = (from DataRow dr in orderProducts.Rows
                                      where Id.Create(dr["RE_Discount_Condition1_Id"]) == memberBdayDiscountId
                                      select dr);
                        //Summing-up the Quanity for this discountCondition
                        foreach(DataRow dr in result)
                        {
                            totalDiscountQty = totalDiscountQty + TypeConvert.ToInt32(dr["Quantity"]);
                        }
                    }

                //Fetch used for the current year for the contact id selected, and subtract from Loyalty Program Tier's (Contact's tier)
                //Birthday Promotion Quota. If no data is found for current year for the contact, the remaining quota would be the same 
                //as the tier quota.
                DataTable memberQuotaUsed = this.DefaultDataAccess.GetDataTable("RE_Member Birthday Discount with Member ? Year ?",
                    new object[] { primaryDataRow["Bill_To_Contact_Id"], DateTime.Now.Year }, "Used");

                    if(memberQuotaUsed != null && memberQuotaUsed.Rows.Count > 0)
                    {
                        //Reverting the Used value back to previous since Re_Order_Status is changed to VOID
                        memberQuotaUsed.Rows[0]["Used"] =   TypeConvert.ToInt32(memberQuotaUsed.Rows[0]["Used"]) - totalDiscountQty;
                        this.DefaultDataAccess.SaveDataTable(memberQuotaUsed);
                    }
                }

                //Checking for Customer Type as Staff
                if (TypeConvert.ToString(primaryDataRow["RE_Order_Status"]).ToUpper() == "VOID" &&
               TypeConvert.ToString(primaryDataRow["RE_Customer_Type"]).ToUpper() == "STAFF" )
                {
                    //Fetching the StaffPurchaseProfile for this Staff
                     DataTable staff = this.DefaultDataAccess.GetDataTable("RE_All Active Staff with Staff Purchase Profile is Defined with IC ?",
                        new object[] { primaryDataRow["RE_Customer_Id"] }, "Staff_Purchase_Profile_Id", "RE_Staff_Id");

                     if (staff != null && staff.Rows.Count == 1)
                     {
                         //Fetching the StaffPurchaseQuata for this StaffPurchaseProfile to get the DiscountCondition applicable for this Staff
                         DataTable staffPurchaseQuota = this.DefaultDataAccess.GetDataTable("RE_Staff Purchase Profile Quota for Staff Purchase Profile ? LOB ?",
                                new object[] { staff.Rows[0]["Staff_Purchase_Profile_Id"], primaryDataRow["RE_LOB_Id"] }, "Quota", "Discount_Condition_Id");
                         
                         if (staffPurchaseQuota != null && staffPurchaseQuota.Rows.Count > 0)
                         {
                             foreach (DataRow drStaffPurchaseQuota in staffPurchaseQuota.Rows)
                             {
                                 Id discountConditionId = Id.Create(drStaffPurchaseQuota["Discount_Condition_Id"]);

                                 if (discountConditionId != null)
                                 {
                                     var result = (from DataRow dr in orderProducts.Rows
                                                   where Id.Create(dr["RE_Discount_Condition1_Id"]) == discountConditionId
                                                   select dr);
                                     //Summing-up the Quanity for this discountCondition
                                     foreach (DataRow dr in result)
                                     {
                                         totalDiscountQty = totalDiscountQty + TypeConvert.ToInt32(dr["Quantity"]);
                                     }
                                 }
                                 //Fetching the Staff Purchase History record to revert this Transaction entries.
                                 DataTable staffPurchase = this.DefaultDataAccess.GetDataTable("RE_Staff Purchase with Staff ?  Discount Condition ? Year ?",
                                                        new object[] { staff.Rows[0]["RE_Staff_Id"], drStaffPurchaseQuota["Discount_Condition_Id"], 
                                                                        DateTime.Now.Year }, DateTime.Now.ToString("MMM") + "_Qty");

                                 if (staffPurchase != null && staffPurchase.Rows.Count > 0)
                                 {
                                     //Reverting the Month's Qty value back to previous since Re_Order_Status is changed to VOID
                                     staffPurchase.Rows[0][DateTime.Now.ToString("MMM") + "_Qty"] = TypeConvert.ToInt32(staffPurchase.Rows[0][DateTime.Now.ToString("MMM") + "_Qty"]) - totalDiscountQty;
                                     this.DefaultDataAccess.SaveDataTable(staffPurchase);
                                     totalDiscountQty = 0;
                                 }

                             }
                         }
                     }
                }
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        /// <summary>
        /// Copy the order details and create a new order.
        /// </summary>
        /// <param name="sfaOrderId">Order which is to be copied</param>
        /// <param name="cashierId">Cashier who is logged into the store</param>
        /// <param name="posId">Store POS.</param>
        /// <returns>New Order Id</returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        public virtual object CreateNewSaleForVoidnNew(Id sfaOrderId, object cashierId, object posId)
        {
            try
            {
                //Create a new Order and copy the details for that.
                DataRow oldOrderRow = this.DefaultDataAccess.GetDataRow("SFA_Order", sfaOrderId, new string[] { });                
                DataRow newOrderRow = this.DefaultDataAccess.GetNewDataRow("SFA_Order", new string[] { });
                //Copy Primaries.
                if (oldOrderRow != null)
                {
                    newOrderRow["RE_Customer_Id"] = oldOrderRow["RE_Customer_Id"];
                    newOrderRow["RE_Staff_Code"] = oldOrderRow["RE_Staff_Code"];
                    newOrderRow["RE_Customer_Type"] = oldOrderRow["RE_Customer_Type"];
                    newOrderRow["RE_Type"] = oldOrderRow["RE_Type"];
                    newOrderRow["RE_LOB_Id"] = oldOrderRow["RE_LOB_Id"];
                    newOrderRow["RE_Tier_Id"] = oldOrderRow["RE_Tier_Id"];
                    newOrderRow["RE_Batch_Id"] = oldOrderRow["RE_Batch_Id"];
                    newOrderRow["Account_Manager_Id"] = oldOrderRow["Account_Manager_Id"];
                    newOrderRow["RE_Total_Qty"] = oldOrderRow["RE_Total_Qty"];
                    newOrderRow["Total_Discount"] = oldOrderRow["Total_Discount"];
                    newOrderRow["Total_Taxes"] = oldOrderRow["Total_Taxes"];
                    newOrderRow["Quote_Sub_Total"] = oldOrderRow["Quote_Sub_Total"];
                    newOrderRow["Quote_Total"] = oldOrderRow["Quote_Total"];
                    newOrderRow["RE_Store_Id"] = oldOrderRow["RE_Store_Id"];
                    newOrderRow["RE_Staff_Id"] = oldOrderRow["RE_Staff_Id"];
                    newOrderRow["Bill_To_Contact_Id"] = oldOrderRow["Bill_To_Contact_Id"];
                    newOrderRow["SFA_Currency_Id"] = oldOrderRow["SFA_Currency_Id"];
                    newOrderRow["RE_Source_Receipt_No"] = oldOrderRow["RE_Source_Receipt_No"];
                    newOrderRow["RE_Source_Order_Id"] = oldOrderRow["RE_Source_Order_Id"];
                    newOrderRow["RE_Gift"] = oldOrderRow["RE_Gift"];
                    newOrderRow["RE_Total_Price_BD"] = oldOrderRow["RE_Total_Price_BD"];
                    newOrderRow["RE_POS_Id"] = posId;
                    newOrderRow["RE_Cashier_Id"] = cashierId;
                    newOrderRow["RE_Receipt_Number"] = GetNewReceiptNumber(oldOrderRow["RE_Store_Id"]);
                    newOrderRow["RE_Order_Date"] = DateTime.Now;
                    newOrderRow["RE_Order_Status"] = "Pending";
                }
                object newOrderId = (this.DefaultDataAccess.SaveDataRow(newOrderRow))["SFA_Order_Id"];
                //Copy Order Products secondary.
                DataTable origOrderProd = this.DefaultDataAccess.GetDataTable("RE_Order Products with Order ?", sfaOrderId,new string[] { });
                DataTable orderProduct = this.DefaultDataAccess.GetDataTable("SFA_Order__Product", new string[] { });
                foreach (DataRow oldOrderProductRow in origOrderProd.Rows)
                {
                    DataRow newOrderProduct = orderProduct.NewRow();
                    newOrderProduct["SFA_Order_Id"] = newOrderId;
                    newOrderProduct["Product_Id"] = oldOrderProductRow["Product_Id"];
                    newOrderProduct["RE_Staff_Code"] = oldOrderProductRow["RE_Staff_Code"];
                    newOrderProduct["RE_Staff_Id"] = oldOrderProductRow["RE_Staff_Id"];
                    newOrderProduct["Quantity"] = oldOrderProductRow["Quantity"];
                    newOrderProduct["RE_Exchange_Reason"] = oldOrderProductRow["RE_Exchange_Reason"];
                    newOrderProduct["RE_Refund_Reason"] = oldOrderProductRow["RE_Refund_Reason"];
                    newOrderProduct["Unit_Price"] = oldOrderProductRow["Unit_Price"];
                    newOrderProduct["Discount_Amount"] = oldOrderProductRow["Discount_Amount"];
                    newOrderProduct["RE_Extended_Price"] = oldOrderProductRow["RE_Extended_Price"];
                    newOrderProduct["RE_Points"] = oldOrderProductRow["RE_Points"];
                    newOrderProduct["RE_Profit"] = oldOrderProductRow["RE_Profit"];
                    newOrderProduct["RE_Revenue"] = oldOrderProductRow["RE_Revenue"];
                    newOrderProduct["RE_Unit_Cost_Price"] = oldOrderProductRow["RE_Unit_Cost_Price"];
                    newOrderProduct["Tax_Amount"] = oldOrderProductRow["Tax_Amount"];
                    newOrderProduct["Tax_Percentage"] = oldOrderProductRow["Tax_Percentage"];
                    newOrderProduct["RE_Storage_Location_Id"] = oldOrderProductRow["RE_Storage_Location_Id"];
                    newOrderProduct["RE_Exclude_In_Net_Sales"] = oldOrderProductRow["RE_Exclude_In_Net_Sales"];
                    newOrderProduct["RE_Invisible"] = oldOrderProductRow["RE_Invisible"];
                    newOrderProduct["RE_Product_Type"] = oldOrderProductRow["RE_Product_Type"];
                    newOrderProduct["RE_Product_Serial_No_Id"] = oldOrderProductRow["RE_Product_Serial_No_Id"];
                    newOrderProduct["RE_Promotion_Id"] = oldOrderProductRow["RE_Promotion_Id"];
                    newOrderProduct["RE_From_Source_Order"] = oldOrderProductRow["RE_From_Source_Order"];
                    newOrderProduct["RE_Source_Qty"] = oldOrderProductRow["RE_Source_Qty"];
                    newOrderProduct["RE_Comments"] = oldOrderProductRow["RE_Comments"];
                    //DS: 17052013 - Copying new fields added through DC and Promotions.
                    newOrderProduct["RE_Item_Scanned"] = oldOrderProductRow["RE_Item_Scanned"];
                    newOrderProduct["RE_Mandatory_Promotion"] = oldOrderProductRow["RE_Mandatory_Promotion"];
                    newOrderProduct["RE_Promo_Ref_Serial"] = oldOrderProductRow["RE_Promo_Ref_Serial"];
                    newOrderProduct["RE_Validated"] = oldOrderProductRow["RE_Validated"];
                    newOrderProduct["Tier1_Discount_Value"] = oldOrderProductRow["Tier1_Discount_Value"];
                    newOrderProduct["Tier1_Discount_Percent"] = oldOrderProductRow["Tier1_Discount_Percent"];
                    newOrderProduct["RE_Authorization_Needed_1"] = oldOrderProductRow["RE_Authorization_Needed_1"];
                    newOrderProduct["RE_Voucher_Number"] = oldOrderProductRow["RE_Voucher_Number"];
                    newOrderProduct["RE_Discount_Condition1_Id"] = oldOrderProductRow["RE_Discount_Condition1_Id"];
                    orderProduct.Rows.Add(newOrderProduct);
                }
                this.DefaultDataAccess.SaveDataTable(orderProduct);

                //Copy Authorization secondary.
                DataTable origAuthorization = this.DefaultDataAccess.GetDataTable("RE_Authorizations for Order?", sfaOrderId, new string[] { });
                DataTable authorization = this.DefaultDataAccess.GetDataTable("RE_Authorization", new string[] { });
                foreach (DataRow origAuthorizationRow in origAuthorization.Rows)
                {
                    DataRow newAuthorizationRow = authorization.NewRow();
                    newAuthorizationRow["Order_Id"] = newOrderId;
                    newAuthorizationRow["Event"] = origAuthorizationRow["Event"];
                    newAuthorizationRow["Authorized"] = origAuthorizationRow["Authorized"];
                    newAuthorizationRow["Comments"] = origAuthorizationRow["Comments"];
                    newAuthorizationRow["RE_Authorized_By_Id"] = origAuthorizationRow["RE_Authorized_By_Id"];
                    authorization.Rows.Add(newAuthorizationRow);
                }
                this.DefaultDataAccess.SaveDataTable(authorization);

                return newOrderId;
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// Get new recipt number for the store.
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        private string GetNewReceiptNumber(object storeId)
        {
            string reciptNumber = string.Empty;
            //Generate New Receipt Number.
            DataTable onlineStoreOfflinePOS = null;
            //DS: For Offline mode, use the Next_Number available on RE_Store_POS, else use the one in RE_Store
            if (SystemServer.SystemInformation.IsMobile)
                onlineStoreOfflinePOS = this.DefaultDataAccess.GetDataTable("RE_POS for Current User", new object[] { }, "Receipt_No_Prefix",
                    "No_Of_Digits", "Next_Number");
            else
                onlineStoreOfflinePOS = this.DefaultDataAccess.GetDataTable("RE_Stores for Store ?", new object[] { storeId },
                    "Receipt_No_Prefix", "No_Of_Digits", "Next_Number");

            if (onlineStoreOfflinePOS != null && onlineStoreOfflinePOS.Rows.Count > 0)
            {
                //DS: When the Next_Number is null, start the series from 1 instead of 0. Remove the '-' from the merging.
                reciptNumber = TypeConvert.ToString(onlineStoreOfflinePOS.Rows[0]["Receipt_No_Prefix"]) +
                    TypeConvert.ToString((Convert.IsDBNull(onlineStoreOfflinePOS.Rows[0]["Next_Number"]) ? 1 : onlineStoreOfflinePOS.Rows[0]["Next_Number"])).
                    PadLeft(TypeConvert.ToInt32(onlineStoreOfflinePOS.Rows[0]["No_Of_Digits"]), '0');

                //DS: 27062013 - Removed the method call and code rewritten here.
                //DS: When the Next_Number is null, start the series from 1 instead of 0.
                onlineStoreOfflinePOS.Rows[0]["Next_Number"] = TypeConvert.ToInt32((Convert.IsDBNull(onlineStoreOfflinePOS.Rows[0]["Next_Number"]) 
                    ? 1 : onlineStoreOfflinePOS.Rows[0]["Next_Number"])) + 1;
                this.DefaultDataAccess.SaveDataTable(onlineStoreOfflinePOS);
            }
            return reciptNumber;
        }

        /// <summary>
        /// Saves the receipt, create the contact and send email.
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    24-02-2013      DS          Initial version for Retail.
        /// </history>
        [TaskExecute]
        public virtual object SaveReceiptAndSendMail(Id orderId, bool createContact)
        {
            object contactId = null;
            try
            {
                //Get Order Details.
                DataRow order = DefaultDataAccess.GetDataRow("SFA_Order", orderId, "RE_Contact_First_Name", "RE_Contact_Last_Name", "RE_Contact_Email",
                    "RE_Contact_Mobile_Phone", "RE_Contact_Home_Phone", "RE_Contact_Address", "RE_Receipt_Attachment", "RE_Receipt_Number", "RE_Store_Id", "RE_LOB_Id",
                    "RE_Batch_Id", "RE_Cashier_Id", "Bill_To_Contact_Id");

                //Generate the Report.
                SystemReport objS = this.SystemServer.GetMetaItem<SystemReport>("RE_Receipt");
                ReportRunner objRunner = this.SystemServer.CreateReportRunner(objS);
                objRunner.ReportJoinType = ReportJoinType.Inner;
                objRunner.ReportOutputFormat = ReportOutputFormat.Pdf;

                byte[] reportReturned = objRunner.Run(ReportFilter.SingleRow, orderId, null);
                if (!Convert.IsDBNull(order["RE_Contact_Email"]) && ValidateEmailAddress(TypeConvert.ToString(order["RE_Contact_Email"])))
                {
                    if (createContact)
                    {
                        DataTable contact = this.DefaultDataAccess.GetDataTable("RE_Contact for Email?", new object[] { order["RE_Contact_Email"] }, "Contact_Id");
                        if (contact == null || contact.Rows.Count == 0)
                        {
                            DataRow newContact = DefaultDataAccess.GetNewDataRow("Contact", "First_Name", "Last_Name", "Email", "Mobile", "Phone", "Address_1", "RE_Source",
                                "RE_Type", "RE_Store_Id", "RE_LOB_Id", "RE_Batch_Id", "RE_Create_Staff_Id", "RE_Brand_Id", "Contact_Id", "RE_Mobile_Number");
                            newContact["First_Name"] = order["RE_Contact_First_Name"];
                            newContact["Last_Name"] = order["RE_Contact_Last_Name"];
                            newContact["Email"] = order["RE_Contact_Email"];                            
                            if (Regex.IsMatch(TypeConvert.ToString(order["RE_Contact_Mobile_Phone"]),"[0-9]"))
                            {
                                newContact["Mobile"] = '+' + TypeConvert.ToString(order["RE_Contact_Mobile_Phone"]);
                                newContact["RE_Mobile_Number"] = order["RE_Contact_Mobile_Phone"];
                            }
                            if (Regex.IsMatch(TypeConvert.ToString(order["RE_Contact_Home_Phone"]), "[0-9]"))
                                newContact["Phone"] = '+' + TypeConvert.ToString(order["RE_Contact_Home_Phone"]);
                            newContact["Address_1"] = order["RE_Contact_Address"];
                            newContact["RE_Source"] = "In Store";
                            newContact["RE_Type"] = "Customer";
                            newContact["RE_Store_Id"] = order["RE_Store_Id"];
                            newContact["RE_LOB_Id"] = order["RE_LOB_Id"];
                            newContact["RE_Brand_Id"] = this.DefaultDataAccess.SqlIndex("RE_Line_Of_Business", "Brand_Id", Id.Create(order["RE_LOB_Id"]));
                            newContact["RE_Batch_Id"] = order["RE_Batch_Id"];
                            newContact["RE_Create_Staff_Id"] = order["RE_Cashier_Id"];

                            order["Bill_To_Contact_Id"] = (DefaultDataAccess.SaveDataRow(newContact))["Contact_Id"];
                        }
                        else if (contact != null && contact.Rows.Count > 0)
                            order["Bill_To_Contact_Id"] = contact.Rows[0]["Contact_Id"];

                        //Return the Contact to the Tender in order to use the same contact in Member creation.
                        contactId = order["Bill_To_Contact_Id"];
                    }
                    try
                    {
                        //Send the Email with the Receipt Attachment.
                        EmailMessage emailMessage = this.SystemServer.CreateMessage();
                        emailMessage.To.Add(TypeConvert.ToString(order["RE_Contact_Email"]));
                        emailMessage.Subject = this.DefaultResourceBundle.GetString("Receipt Email Subject", new string[] { TypeConvert.ToString(order["RE_Receipt_Number"]), 
                        DateTime.Today.ToString("dd/MM/yyyy") });
                        emailMessage.IsBodyHtml = true;
                        emailMessage.Body = this.DefaultResourceBundle.GetString("Receipt Email Body", new string[] { TypeConvert.ToString(order["RE_Contact_First_Name"]), 
                        DateTime.Today.ToString("dd/MM/yyyy"), TypeConvert.ToString(order["RE_Receipt_Number"])});
                        EmailMessageAttachment attachment = new EmailMessageAttachment(reportReturned, order["RE_Receipt_Number"] + ".pdf");
                        emailMessage.Attachments.Add(attachment);
                        emailMessage.Send();
                    }
                    catch (Exception)
                    { }
                }

                //DS: 20052013 - No need to save the attachment as it unnecessarily increases the DB size.
                //DataTemplate dataTemplate = this.SystemServer.GetMetaItem<DataTemplate>("RE_Sale – Walk In");
                //Column attachmentColumn = dataTemplate.PrimaryDataSection.Table.Columns["RE_Receipt_Attachment"];
                //AttachmentInformation attachInfo = this.SystemServer.AttachmentService.GetAttachmentInformation(attachmentColumn, order);
                //attachInfo.SetAttachment(order["RE_Receipt_Number"] + ".pdf", reportReturned, DateTime.Now);
                DefaultDataAccess.SaveDataRow(order);
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
            return contactId;
        }

        /// <summary>
        /// Send Email to Finance for Deposit canceellation and Forfeit.
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    24-02-2013      DS          Initial version for Retail.
        /// 6.0.12.2    16-08-2013      DS          Change in method definition for Deposit parameters for email.
        /// </history>
        [TaskExecute]
        public void SendFinanceEmailForDeposit(string ReceiptNumber, string DepositStatus, DateTime DepositDate, string DepositAmount)
        {
            try
            {
                //Get Finance Email
                string financeEmail = TypeConvert.ToString(DefaultDataAccess.SqlIndex("RE_Line_Of_Business", "Finance_Email",
                    Id.Create(DefaultDataAccess.SqlIndex("Employee", "RE_Line_Of_Business_Id", SystemServer.UserProfile.EmployeeId))));
                if (ValidateEmailAddress(financeEmail))
                {
                    EmailMessage emailMessage = this.SystemServer.CreateMessage();
                    emailMessage.To.Add(financeEmail);
                    emailMessage.IsBodyHtml = true;
                    if (string.Equals(DepositStatus, "Cancel"))
                    {
                        //DS: 16082013 - New parameters are added to the Deposit Mail.
                        emailMessage.Subject = this.DefaultResourceBundle.GetString("Cancelled Deposit Finance Email Subject", new string[] { ReceiptNumber, 
                            DateTime.Today.ToString("dd/MM/yyyy"), DepositDate.ToString("dd/MM/yyyy"), DepositAmount});
                        emailMessage.Body = this.DefaultResourceBundle.GetString("Cancelled Deposit Finance Email Body", new string[] { ReceiptNumber,
                            DateTime.Today.ToString("dd/MM/yyyy"), DepositDate.ToString("dd/MM/yyyy"), DepositAmount});
                    }
                    else if (string.Equals(DepositStatus, "Forfeit"))
                    {
                        //DS: 16082013 - New parameters are added to the Deposit Mail.
                        emailMessage.Subject = this.DefaultResourceBundle.GetString("Forfeited Deposit Finance Email Subject", new string[] { ReceiptNumber, 
                            DateTime.Today.ToString("dd/MM/yyyy"), DepositDate.ToString("dd/MM/yyyy"), DepositAmount});
                        emailMessage.Body = this.DefaultResourceBundle.GetString("Forfeited Deposit Finance Email Body", new string[] { ReceiptNumber,
                            DateTime.Today.ToString("dd/MM/yyyy"), DepositDate.ToString("dd/MM/yyyy"), DepositAmount});
                    }
                    emailMessage.Send();
                }
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// Validate Email Address before sending out the Email.
        /// </summary>
        /// <param name="emailAddress"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date            Author      Description
        /// 6.0.12.1    18-02-2013      DS          Initial version for Retail.
        /// </history>
        private bool ValidateEmailAddress(string emailAddress)
        {
            if (!string.IsNullOrEmpty(emailAddress) && (emailAddress.Length > 0))
            {
                //DS: 16082013 - Changed the Email Validation for accepting multiple emails separated by ';'. If any of the Id's are not valid, then do not send email to any.
                //Regex regex = new Regex(@"^([\w]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z]([-\w]*[0-9a-zA-Z])*\.)+[0-9a-zA-Z]{2,9})$");
                Regex regex = new Regex(@"^[\W]*([\w+\-.%]+@[\w\-.]+\.[A-Za-z]{2,4}[\W]*;{1}[\W]*)*([\w+\-.%]+@[\w\-.]+\.[A-Za-z]{2,4})[\W]*$");
                return regex.IsMatch(emailAddress);
            }
            return true;
        }
        
        #region Apple Care Functions

        /// <summary>
        /// 
        /// </summary>
        /// <param name="primaryDataRow"></param>
        /// <param name="orderProducts"></param>        
        private DataRow AddRAETransactionRecord( DataRow drAppleCareProduct, string source, string firstName, string lastName, string email, string phone, string address1, string address2, string city, string state,
            string zip,string country,string shipTo,string dateOfPurchase)
        {
            try
            {
                string purchaseMode = string.Empty;
                string purchaseOrderNumber = string.Empty;

                //getting new row for RE_RAE_Transaction.
                DataTable raeTransaction = this.DefaultDataAccess.GetNewDataTable("RE_RAE_Transaction", new string[] { });
                DataRow raeTransactionRow = raeTransaction.NewRow();
                
                raeTransactionRow["Source_"] = source;

                //In case of AIRPORT STORES Sale fetching data from RE_RAE_Transaction record.
                if (source.ToUpper() == "AIRPORT STORES" || source.ToUpper() == "HQ")
                {
                    raeTransactionRow["SFA_Order_Product_Id"] = drAppleCareProduct["SFA_Order_Product_Id"];
                    purchaseMode = TypeConvert.ToString(drAppleCareProduct["Purchase_Mode"]);
                    purchaseOrderNumber = TypeConvert.ToString(drAppleCareProduct["Purchase_Order_No"]);

                    raeTransactionRow["Primary_Serial_Number"] = drAppleCareProduct["Primary_Serial_Number"];
                    raeTransactionRow["Secondary_Serial_Number"] = drAppleCareProduct["Secondary_Serial_Number"];
                }
                else//In case of TOWN STORES Sale fetching data from SFA_Order__Product record.                
                {
                    raeTransactionRow["SFA_Order_Product_Id"] = drAppleCareProduct["SFA_Order__Product_Id"];
                    purchaseMode = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Purchase_Mode"]);
                    //Setting purchaseOrderNumber depeding on Qty. If Qty >0 then set from RE_PO_Number(Sale) else from RE_Original_PO_Number(exchange/refnd)
                    purchaseOrderNumber = (TypeConvert.ToInt32(drAppleCareProduct["Quantity"]) > 0 ? TypeConvert.ToString(drAppleCareProduct["RE_PO_Number"]) :
                                            TypeConvert.ToString(drAppleCareProduct["RE_Original_PO_Number"]));

                    raeTransactionRow["Primary_Serial_Number"] = drAppleCareProduct["RE_RAE_Serial_Number"];
                    raeTransactionRow["Secondary_Serial_Number"] = drAppleCareProduct["RE_RAE_Sec_Serial_No"];
                }

                //Setting below values as per Qty. If Qty > 0 then set rae_Transaction as "CreateAEOrder" and set necessary parameters
                if (TypeConvert.ToInt32(drAppleCareProduct["Quantity"]) > 0)
                {
                    raeTransactionRow["RAE_Transaction"] = "CreateAEOrder";
                    raeTransactionRow["Contact_First_Name"] = firstName;
                    raeTransactionRow["Contact_Last_Name"] = lastName;
                    raeTransactionRow["Contact_Address_1"] = address1;
                    raeTransactionRow["Contact_Address_2"] = address2;
                    raeTransactionRow["Contact_Address_City"] = city;
                    raeTransactionRow["Contact_Address_State"] = "SG";
                    raeTransactionRow["Contact_Address_Zip"] = zip;
                    raeTransactionRow["Contact_Address_Country"] = country;
                    raeTransactionRow["Contact_Email"] = email;
                    raeTransactionRow["Contact_Phone"] = phone;
                    raeTransactionRow["Purchase_Mode"] = purchaseMode;
                    raeTransactionRow["Date_of_Purchase"] = dateOfPurchase;
                    raeTransactionRow["POC_Delivery_Preference"] = "E";
                    raeTransactionRow["POC_Language_Preference"] = "ENG";
                    raeTransactionRow["Purchase_Order_No"] = purchaseOrderNumber;
                }
                else//If Qty < 0 then set rae_Transaction as "CancelAEOrder" and set necessary parameters
                {
                    raeTransactionRow["RAE_Transaction"] = "CancelAEOrder";
                    raeTransactionRow["Purchase_Order_No"] = purchaseOrderNumber;
                    raeTransactionRow["Return_Date"] = DateTime.Today;
                }
                
                raeTransactionRow["Ship_To"] = shipTo;
                //raeTransactionRow["Agreement_Number"] = agreementNumber;

                raeTransaction.Rows.Add(raeTransactionRow);

                //saving the record in RE_RAE_Transaction
                raeTransactionRow = this.DefaultDataAccess.SaveDataRow(raeTransactionRow);

                return raeTransactionRow;
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="primaryDataRow"></param>
        /// <param name="orderProducts"></param>        
        private object UpdateRAETransactionRecord(DataRow drAppleCareProduct, string agreementNumber,Id recordId)
        {
            try
            {
                string purchaseMode = string.Empty;
                string purchaseOrderNumber = string.Empty;

                //getting new row for RE_RAE_Transaction.
                DataRow raeTransactionRow = this.DefaultDataAccess.GetDataRow("RE_RAE_Transaction", recordId, new string[] { });

                raeTransactionRow["SFA_Order_Product_Id"] = drAppleCareProduct["SFA_Order_Product_Id"];
                raeTransactionRow["Contact_First_Name"] = drAppleCareProduct["Contact_First_Name"];
                raeTransactionRow["Contact_Last_Name"] = drAppleCareProduct["Contact_Last_Name"];
                raeTransactionRow["Contact_Email"] = drAppleCareProduct["Contact_Email"];
                raeTransactionRow["Contact_Phone"] = drAppleCareProduct["Contact_Phone"];

                raeTransactionRow["Source_"] = drAppleCareProduct["Source_"];
                raeTransactionRow["RAE_Transaction"] = drAppleCareProduct["RAE_Transaction"];
                raeTransactionRow["Purchase_Order_No"] = drAppleCareProduct["Purchase_Order_No"];
                raeTransactionRow["Primary_Serial_Number"] = drAppleCareProduct["Primary_Serial_Number"];
                raeTransactionRow["Secondary_Serial_Number"] = drAppleCareProduct["Secondary_Serial_Number"];
                raeTransactionRow["Date_of_Purchase"] = drAppleCareProduct["Date_of_Purchase"];

                raeTransactionRow["Agreement_Number"] = agreementNumber;

                //saving the record in RE_RAE_Transaction
                raeTransactionRow = this.DefaultDataAccess.SaveDataRow(raeTransactionRow);

                return raeTransactionRow["RE_RAE_Transaction_Id"];
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="raeTranscationId"></param>
        /// <param name="apiCalled"></param>
        /// <param name="requestXML"></param>
        /// <param name="responseXML"></param>        
        private void AddRAETrancationLogRecord(object raeTranscationId, string apiCalled, StringBuilder requestXML,StringBuilder responseXML)
        {
            try
            {
                DataRow drRaeTransactionLog = this.DefaultDataAccess.GetNewDataRow("RE_RAE_Transaction_Log", new string[] { });

                drRaeTransactionLog["RAE_Transaction_Id"] = raeTranscationId;
                drRaeTransactionLog["Log_Time"] = DateTime.Now;
                drRaeTransactionLog["API_Called"] = apiCalled;
                drRaeTransactionLog["Request_XML"] = requestXML.ToString();
                drRaeTransactionLog["Response_XML"] = responseXML.ToString();

                drRaeTransactionLog = this.DefaultDataAccess.SaveDataRow(drRaeTransactionLog);                
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="appleCareService"></param>
        /// <param name="lobId"></param>
        /// <returns></returns>
        private AppleCare.authenticateResponseType CallAppleCareAuthenticate(AppleCare.GsxWSApacResellerService appleCareService, DataRow drLOB)
        {
            try
            {
                AppleCare.authenticateRequestType ar = new AppleCare.authenticateRequestType();
                ar.userId = TypeConvert.ToString(drLOB["RE_RAE_User_Id"]);
                ar.password = TypeConvert.ToString(drLOB["RE_RAE_Password"]);
                ar.serviceAccountNo = TypeConvert.ToString(drLOB["RE_RAE_ServiceAccountNo"]);
                ar.languageCode = TypeConvert.ToString(drLOB["RE_RAE_LanguageCode"]);
                ar.userTimeZone = TypeConvert.ToString(drLOB["RE_RAE_UserTimeZone"]);

                //Calling Authenticate webserice to get the UserSession information.
                //this session will be active till 30 mins.
                AppleCare.authenticateResponseType response = appleCareService.Authenticate(ar);

                return response;
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        /// <summary>
        /// Will get called from Sales-Client task.
        /// Will create an Apple Care transaction, if it is a Processed Sale, with atleast one Apple Care product in secondary.
        /// Will be used for both - ConCurrent Sales and INstallBase Sale, when Apple Care Item is added on Sales form.
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [TaskExecute]
        public string[,] CreateAppleCareProduct(DataSet data)
        {
            try
            {
                DataRow primaryRow = data.Tables[0].Rows[0];
                
                if (string.Equals(TypeConvert.ToString(primaryRow["RE_Order_Status"]), "Processed"))
                {
                    DataTable orderProduct = data.Tables["SFA_Order__Product_SFA_Order_I"];
                    DataRow[] appleCareProducts = orderProduct.AsEnumerable().Where(a => a["RE_RAE_Serial_Number"] != DBNull.Value).ToArray();
                    //Check if Apple Care Produtcs exists in this Order record.
                    if (appleCareProducts != null && appleCareProducts.Length > 0)
                    {
                        string[,] returnValues = CreateAppleCareProduct(primaryRow, data.Tables["SFA_Order__Product_SFA_Order_I"], appleCareProducts);

                        return returnValues;
                    }
                }
                return null;
            }
            catch (Exception exc)
            {   
                throw new PivotalApplicationCoreException(exc.Message, exc);
                return null;
            }
        }

        /// <summary>
        /// Will create an Apple Care transaction in RE_RAE_Transaction.
        /// Will call the Apple Care webservice method CreateAEOrder/CancelAEOrder depending on the Quantity for the OrderProduct seconadry record.
        /// Will log the return parameters in RE_RAE_Transaction_Log table.
        /// </summary>
        /// <param name="primaryDataRow"></param>
        /// <param name="orderProducts"></param>
        /// <param name="appleCareProducts"></param>        
        private string[,] CreateAppleCareProduct(DataRow primaryDataRow, DataTable orderProducts, DataRow[] appleCareProducts)
        {
            try
            {
                string[,] returnValues = new string[appleCareProducts.Length,2];

                string agreementNumbers = string.Empty;

                string address1; string address2; string city; string state; string zip; string country; string phone; string shipTo;
                string firstName; string lastName; string email;
                firstName = lastName = email = address1 = address2 = city = state = zip = country = phone = shipTo = string.Empty;
                StringBuilder requestXML; StringBuilder responseXML;

                if (appleCareProducts != null && appleCareProducts.Length > 0)
                {                   
                    //Get details from LOB.
                    DataRow drLOB = this.DefaultDataAccess.GetDataRow("RE_Line_Of_Business", Id.Create(primaryDataRow["RE_LOB_Id"]), new string[] { "RE_RAE_ShipTo", "RE_RAE_WebService_URL"});                    
                    
                    //Initialize AppleCareService using the URL from LOB
                    AppleCare.GsxWSApacResellerService appleCareService = new AppleCare.GsxWSApacResellerService();
                    appleCareService.Url = TypeConvert.ToString(drLOB["RE_RAE_WebService_URL"]);
                    shipTo = TypeConvert.ToString(drLOB["RE_RAE_ShipTo"]);

                    //Get Contact details from Store
                    DataRow drStore = this.DefaultDataAccess.GetDataRow("RE_Store", Id.Create(primaryDataRow["RE_Store_Id"]), new string[] { "Address_1", "Address_2", "City", "State_", "Postal_Code", "Country", "Phone" });
                    
                    firstName = TypeConvert.ToString(primaryDataRow["RE_Contact_First_Name"]);
                    lastName = TypeConvert.ToString(primaryDataRow["RE_Contact_Last_Name"]);
                    email = TypeConvert.ToString(primaryDataRow["RE_Contact_Email"]);
                    phone = TypeConvert.ToString(Convert.IsDBNull(primaryDataRow["RE_Contact_Home_Phone"]) ? primaryDataRow["RE_Contact_Mobile_Phone"] : primaryDataRow["RE_Contact_Home_Phone"]);
                    //Getting Address from Store when saved from Sales Form.
                    address1 = TypeConvert.ToString(drStore["Address_1"]);
                    address2 = TypeConvert.ToString(drStore["Address_2"]);
                    city = TypeConvert.ToString(drStore["City"]);
                    state = TypeConvert.ToString(drStore["State_"]);
                    zip = TypeConvert.ToString(drStore["Postal_Code"]);
                    country = TypeConvert.ToString(drStore["Country"]);

                    if (phone == string.Empty)
                        phone = TypeConvert.ToString(drStore["Phone"]);
                    
                    //Setting dateOfPurchase as CurreantDate in mm/dd/yy format.
                    string dateOfPurchase = DateTime.Today.Month.ToString().PadLeft(2, '0') + "/" + DateTime.Today.Day.ToString().PadLeft(2, '0') + "/" + DateTime.Today.Year.ToString().Substring(2, 2);                    
                    
                    int rowIndex= 0;
                    foreach (DataRow dr in appleCareProducts)
                    {
                        //Adding a record in RE_RAE_Transaction with the respose agreement number filled in
                        DataRow raeTransactionRow = AddRAETransactionRecord(dr, "Town Stores", firstName, lastName, email, phone, address1, address2, city, state, zip, country,
                                    shipTo, dateOfPurchase);

                        object raeTransactionId = raeTransactionRow["RE_RAE_Transaction_Id"];

                        //Calling Apple Care CreateAEOrder/CancelAEOrder depending on the Quantity for the OrderProduct seconadry record
                        //If Webservice call is SUCCESS it will return the agreement Number
                        string agreementNumber = this.CallAppleCareCreateOrCancelOrder(appleCareService, AppleCareUserSessionId, dr, "Town Stores", firstName,
                            lastName, email, phone, address1, address2, city, state, zip, country, shipTo, dateOfPurchase, true, out requestXML, out responseXML);                        

                        if (StringBuilder.Equals(requestXML,string.Empty) && StringBuilder.Equals(responseXML ,string.Empty))
                        {
                            //Adding a record in RE_RAE_Transaction_Log for the RE_RAE_Transcation_Id created before this.
                            //This log will also contain the request and the response XML.
                            this.AddRAETrancationLogRecord(raeTransactionId, (TypeConvert.ToInt32(dr["Quantity"]) > 0 ? "CreateAEOrder" : "CancelAEOrder"), requestXML, responseXML);
                        }
                        
                        if (agreementNumber != string.Empty)
                        {
                            //Updating the AgreementNumber is OrderProduct secondary row in case of SUCCESSFULL transaction.
                            //Setting the AgreementNumber & registration Date in OrderProduct if agreementNumber exists.
                            this.SetAgreementNoAndRegistrationDateInAppleCareProduct(agreementNumber, Id.Create(dr["SFA_Order__Product_Id"]));
                            //Setting Agreement Number in RE_RAE_Transaction record.
                            this.SaveRAETransactionRecord(raeTransactionRow, agreementNumber);
                        }

                        returnValues[rowIndex, 0] = TypeConvert.ToString(dr["RE_RAE_Serial_Number"]);
                        returnValues[rowIndex, 1] = agreementNumber;
                        rowIndex++;
                    }
                }

                return returnValues;
            }
            catch (Exception exc)
            {                
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        /// <summary>
        /// Setting the AgreementNumber & registration Date in OrderProduct if agreementNumber exists.
        /// </summary>
        /// <param name="agreementNumber"></param>
        /// <param name="orderProductId"></param>
        private void SetAgreementNoAndRegistrationDateInAppleCareProduct(string agreementNumber, Id orderProductId)
        {
            try
            {
                DataRow drOrderProduct = this.DefaultDataAccess.GetDataRow("SFA_Order__Product", orderProductId, new string[] { "RE_Registration_Date", "RE_RAE_Agreement_Number" });

                drOrderProduct["RE_RAE_Agreement_Number"] = agreementNumber;
                drOrderProduct["RE_Registration_Date"] = DateTime.Today;
                //Saving the Orderproduct record with agreement Number.
                this.DefaultDataAccess.SaveDataRow(drOrderProduct);
            }
            catch (Exception ex)
            {
                throw new PivotalApplicationCoreException(ex.Message, ex);
            }
        }
                
        /// <summary>
        /// Will Call Apple Care CreateAEOrder/CancelAEOrder depending on the Quantity for the OrderProduct seconadary record
        /// If Webservice call is SUCCESS it will return the agreement Number
        /// </summary>
        /// <param name="appleCareService"></param>
        /// <param name="userSessionId"></param>
        /// <param name="drAppleCareProduct"></param>
        /// <param name="source"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <param name="email"></param>
        /// <param name="phone"></param>
        /// <param name="address1"></param>
        /// <param name="address2"></param>
        /// <param name="city"></param>
        /// <param name="state"></param>
        /// <param name="zip"></param>
        /// <param name="country"></param>
        /// <param name="shipTo"></param>
        /// <param name="dateOfPurchase"></param>
        /// <param name="concurrentSale"></param>
        /// <param name="requestXML"></param>
        /// <param name="responseXML"></param>
        /// <returns></returns>
        private string CallAppleCareCreateOrCancelOrder(AppleCare.GsxWSApacResellerService appleCareService, string userSessionId, DataRow drAppleCareProduct, 
            string source, string firstName, string lastName, string email, string phone, string address1, string address2, string city, string state,
            string zip, string country, string shipTo, string dateOfPurchase, bool concurrentSale, out StringBuilder requestXML, out StringBuilder responseXML)
        {
            responseXML = new StringBuilder();
            requestXML = new StringBuilder();
            try
            {
                if (userSessionId != string.Empty)
                {
                    //Calling CreateAEOrder for +ve Quantity.   
                    if (TypeConvert.ToInt32(drAppleCareProduct["Quantity"]) > 0)
                    {
                        AppleCare.createAEOrderRequestType createOrderRequestType = new AppleCare.createAEOrderRequestType();
                        AppleCare.gsxUserSessionType sessionType = new AppleCare.gsxUserSessionType();

                        sessionType.userSessionId = userSessionId;
                        createOrderRequestType.userSession = sessionType;

                        //Initializing the CreateAEOrderRequset parameter and passing valid values.
                        aeOrderRequestInfoType orderData = new aeOrderRequestInfoType();
                        aeRequestPart requestPart = new aeRequestPart();
                        orderData.addressLine1 = address1;
                        orderData.addressLine2 = address2;
                        orderData.city = city;
                        orderData.shipTo = shipTo;
                        orderData.state = "ZZ";
                        orderData.zipCode = zip;
                        orderData.country = "SG";
                        orderData.dateOfPurchase = dateOfPurchase;
                        orderData.emailAddress = email;
                        orderData.firstName = firstName;
                        orderData.lastName = lastName;
                        orderData.pocDeliveryPreference = "E";
                        orderData.pocLanguage = "ENG";
                        orderData.primaryPhone = phone;
                        //In case of Concurrent Sale fetching data from SFA_Order__Product record.
                        if (concurrentSale)
                        {
                            orderData.purchaseMode = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Purchase_Mode"]);
                            orderData.purchaseOrder = TypeConvert.ToString(drAppleCareProduct["RE_PO_Number"]);
                            requestPart.serialNumber = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Serial_Number"]);
                            requestPart.secondarySerialNumber = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Sec_Serial_No"]);
                        }
                        else//In case of Installbase Sale fetching data from RE_RAE_Transaction record.
                        {
                            orderData.purchaseMode = TypeConvert.ToString(drAppleCareProduct["Purchase_Mode"]);
                            orderData.purchaseOrder = TypeConvert.ToString(drAppleCareProduct["Purchase_Order_No"]);
                            requestPart.serialNumber = TypeConvert.ToString(drAppleCareProduct["Primary_Serial_Number"]);
                            requestPart.secondarySerialNumber = TypeConvert.ToString(drAppleCareProduct["Secondary_Serial_Number"]);
                        }

                        orderData.requestPart = requestPart;
                        createOrderRequestType.orderData = orderData;

                        //Getting the CreateAEOrder request XML
                        requestXML = this.GetXML("CreateAEOrder-Request", createOrderRequestType);

                        //Calling the CreateAEOrder Webservice with necessary parameters.
                        AppleCare.createAEOrderResponseType createOrderResponseType = appleCareService.CreateAEOrder(createOrderRequestType);

                        //Getting the CreateAEOrder response XML
                        responseXML = this.GetXML("CreateAEOrder-Response", createOrderResponseType);

                        //Returning the agreement number from the Webservice call.
                        return createOrderResponseType.orderConfirmation.agreementNumber;
                    }
                    else //Calling CancelAEOrder for -ve Quantity.   
                    {
                        AppleCare.cancelAEOrderRequestType cancelRequest = new AppleCare.cancelAEOrderRequestType();
                        AppleCare.gsxUserSessionType sessionType = new AppleCare.gsxUserSessionType();
                        sessionType.userSessionId = userSessionId;
                        cancelRequest.userSession = sessionType;

                        //Initializing the CancelAEOrderRequset parameter and passing valid values.
                        aeOrderCancelRequestInfoType orderData = new aeOrderCancelRequestInfoType();
                        aeRequestPart requestPart = new aeRequestPart();

                        orderData.shipTo = shipTo;
                        orderData.returnDate = DateTime.Today.Month.ToString().PadLeft(2, '0') + "/" + DateTime.Today.Day.ToString().PadLeft(2, '0') + "/" + DateTime.Today.Year.ToString().Substring(2, 2);

                        //In case of Concurrent Sale fetching data from SFA_Order__Product record.
                        if (concurrentSale)
                        {
                            requestPart.serialNumber = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Serial_Number"]);
                            requestPart.secondarySerialNumber = TypeConvert.ToString(drAppleCareProduct["RE_RAE_Sec_Serial_No"]);
                            orderData.purchaseOrder = TypeConvert.ToString(drAppleCareProduct["RE_Original_PO_Number"]);
                        }
                        else//In case of Installbase Sale fetching data from RE_RAE_Transaction record.
                        {
                            requestPart.serialNumber = TypeConvert.ToString(drAppleCareProduct["Primary_Serial_Number"]);
                            requestPart.secondarySerialNumber = TypeConvert.ToString(drAppleCareProduct["Secondary_Serial_Number"]);
                            orderData.purchaseOrder = TypeConvert.ToString(drAppleCareProduct["Purchase_Order_No"]);
                        }
                        orderData.requestPart = requestPart;
                        cancelRequest.orderData = orderData;

                        //Getting the CancelAEOrder request XML
                        requestXML = this.GetXML("CancelAEOrder-Request", cancelRequest);

                        //Calling the CancelAEOrder Webservice with necessary parameters.
                        AppleCare.cancelAEOrderResponseType cancelResponse = appleCareService.CancelAEOrder(cancelRequest);

                        //Getting the CancelAEOrder response XML
                        responseXML = this.GetXML("CancelAEOrder-Response", cancelResponse);

                        //Returning the agreement number from the Webservice call.
                        return cancelResponse.cancelOrderConfirmation.agreementNumber;
                    }
                }
                else
                    return string.Empty;
            }
            catch (Exception exc)
            {
                //Returing the error Message as responseXML in case of ERROR.
                responseXML.Append(exc.Message);
                return string.Empty;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="typeObject"></param>
        /// <returns></returns>
        private StringBuilder GetXML(string type, object typeObject)
        {
            try
            {
                StringBuilder xml = new StringBuilder();
                switch (type)
                {
                    case "CreateAEOrder-Request":
                        {
                            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(AppleCare.createAEOrderRequestType));

                            // Serializing the returned object
                            XmlWriter xmlWriter = XmlWriter.Create(xml);
                            ser.Serialize(xmlWriter, typeObject);

                            return xml;
                        }
                    case "CreateAEOrder-Response":
                        {
                            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(AppleCare.createAEOrderResponseType));

                            // Serializing the returned object
                            XmlWriter xmlWriter = XmlWriter.Create(xml);
                            ser.Serialize(xmlWriter, typeObject);

                            return xml;
                        }
                    case "CancelAEOrder-Request":
                        {
                            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(AppleCare.cancelAEOrderRequestType));

                            // Serializing the returned object
                            XmlWriter xmlWriter = XmlWriter.Create(xml);
                            ser.Serialize(xmlWriter, typeObject);

                            return xml;
                        }
                    case "CancelAEOrder-Response":
                        {
                            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(AppleCare.cancelAEOrderResponseType));

                            // Serializing the returned object
                            XmlWriter xmlWriter = XmlWriter.Create(xml);
                            ser.Serialize(xmlWriter, typeObject);

                            return xml;
                        }
                    default:
                        return null;
                }
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message,exc);
            }
        }

        private object SaveRAETransactionRecord(DataRow raeTransactionRow, string agreementNumber)
        {
            try
            {
                raeTransactionRow["Agreement_Number"] = agreementNumber;
                //saving the record in RE_RAE_Transaction
                raeTransactionRow = this.DefaultDataAccess.SaveDataRow(raeTransactionRow);

                return raeTransactionRow["RE_RAE_Transaction_Id"];
            }
            catch(Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        /// <summary>
        /// Will get called from RE_RAE_Transaction-Client task.
        /// Will be used for New AppleCare Transcation at Airport counters.
        /// Will be used for any FAILED transactions from TownStores and Airport counters.
        /// </summary>
        /// <param name="primaryDataTable"></param>
        /// <param name="recordId"></param>
        /// <returns></returns>
        [TaskExecute]
        public Id CallAppleCareCreateOrCancelOrder(DataTable primaryDataTable,Id recordId)
        {
            try
            {
                DataRow primaryDataRow = primaryDataTable.Rows[0];
                string address1; string address2; string city; string state; string zip; string country; string phone; string dateOfPurchase;string shipTo ;
                string firstName; string lastName; string email;
                address1 = address2 = city = state = zip = country = phone = firstName = lastName = email = dateOfPurchase = shipTo = string.Empty;
                StringBuilder requestXML; StringBuilder responseXML;

                //Getting CurrentEmployee address information in case of Installbase sale.
                DataRow drCurrentEmployee = this.DefaultDataAccess.GetDataRow("Employee", this.SystemServer.UserProfile.EmployeeId, new string[] {"RE_Line_Of_Business_Id", "Address_1", "Address_2", "City", "State_", "Zip", "Country", "Work_Phone", });

                //Get details from LOB.
                DataRow drLOB = this.DefaultDataAccess.GetDataRow("RE_Line_Of_Business", Id.Create(drCurrentEmployee["RE_Line_Of_Business_Id"]), new string[] { "RE_RAE_ShipTo", "RE_RAE_WebService_URL"});
                //Initialize AppleCareService using the URL from LOB
                AppleCare.GsxWSApacResellerService appleCareService = new AppleCare.GsxWSApacResellerService();
                appleCareService.Url = TypeConvert.ToString(drLOB["RE_RAE_WebService_URL"]);
                shipTo = TypeConvert.ToString(drLOB["RE_RAE_ShipTo"]);
              
                firstName = TypeConvert.ToString(primaryDataRow["Contact_First_Name"]);
                lastName = TypeConvert.ToString(primaryDataRow["Contact_Last_Name"]);
                email = TypeConvert.ToString(primaryDataRow["Contact_Email"]);
                dateOfPurchase = TypeConvert.ToString(primaryDataRow["Date_of_Purchase"]);

                //Getting Address from Employee when it is a Installbase transaction.
                address1 = TypeConvert.ToString(drCurrentEmployee["Address_1"]);
                address2 = TypeConvert.ToString(drCurrentEmployee["Address_2"]);
                city = TypeConvert.ToString(drCurrentEmployee["City"]);
                state = TypeConvert.ToString(drCurrentEmployee["State_"]);
                zip = TypeConvert.ToString(drCurrentEmployee["Zip"]);
                country = TypeConvert.ToString(drCurrentEmployee["Country"]);
                phone = TypeConvert.ToString(primaryDataRow["Contact_Phone"]);

                if (phone == string.Empty)
                    phone = TypeConvert.ToString(drCurrentEmployee["Work_Phone"]);
               
                object raeTransactionId = null;

                //Setting the orderproductId varaible.
                //If the value exists then it a a RETRY case(The Webservice call failed while ProcessSale.Now the user is trying to call the Webservice again to get the agreementNumber.
                Id orderproductId = Id.Create(primaryDataRow["SFA_Order_Product_Id"]);
                DataRow raeTransactionRow = null;
                if (recordId == null)
                {
                    raeTransactionRow = AddRAETransactionRecord(primaryDataRow, TypeConvert.ToString(primaryDataRow["Source_"]), firstName, lastName, email, phone, address1, address2, city, state, zip, country, shipTo, dateOfPurchase);                    
                }

                string agreementNumber = this.CallAppleCareCreateOrCancelOrder(appleCareService, AppleCareUserSessionId, primaryDataRow, TypeConvert.ToString(primaryDataRow["Source_"]), firstName, lastName, email, phone, address1, address2, city, state, zip, country, shipTo, dateOfPurchase, false, out requestXML, out responseXML);

                //if orderproductId is null. Then its is a new AplleCareProduct sale.
                //Adding a record in RE_RAE_Transaction with the respose agreement number filled in                
                if (recordId == null)
                {                    
                    raeTransactionId = this.SaveRAETransactionRecord(raeTransactionRow, agreementNumber);
                }
                else
                {
                    this.UpdateRAETransactionRecord(primaryDataRow, agreementNumber, recordId);
                    raeTransactionId = primaryDataRow["RE_RAE_Transaction_Id"];
                }
                //Adding a record in RE_RAE_Transaction_Log for the RE_RAE_Transcation_Id created before this.
                //This log will also contain the request and the response XML.
                this.AddRAETrancationLogRecord(raeTransactionId, (TypeConvert.ToInt32(primaryDataRow["Quantity"]) > 0 ? "CreateAEOrder" : "CancelAEOrder"), requestXML, responseXML);

                //Updating the AgreementNumber is OrderProduct secondary row in case of SUCCESSFULL transaction.
                this.SetAgreementNoAndRegistrationDateInAppleCareProduct(agreementNumber, orderproductId);

                //Retruning the raeTransactionId.
                return Id.Create(raeTransactionId);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        #region Apple Care Authentication

        private void AppleCareAuthenticate()
        {
            try
            {
                DateTime currentTime = DateTime.Now;
                DateTime activeSession = AppleCareSessionDateTime.AddMinutes(25);

                if (activeSession <= currentTime)
                {  
                    DataRow drLOB =  this.DefaultDataAccess.GetDataTable("RE_Logged In Employee LOB", new object[] {SystemServer.UserProfile.EmployeeId}, new string[] { "RE_RAE_WebService_URL",
                                                          "RE_RAE_User_Id","RE_RAE_Password","RE_RAE_ServiceAccountNo","RE_RAE_LanguageCode","RE_RAE_UserTimeZone"}).Rows[0];

                    AppleCare.GsxWSApacResellerService appleCareService = new AppleCare.GsxWSApacResellerService();
                    appleCareService.Url = TypeConvert.ToString(drLOB["RE_RAE_WebService_URL"]);

                    AppleCare.authenticateRequestType ar = new AppleCare.authenticateRequestType();
                    ar.userId = TypeConvert.ToString(drLOB["RE_RAE_User_Id"]);
                    ar.password = TypeConvert.ToString(drLOB["RE_RAE_Password"]);
                    ar.serviceAccountNo = TypeConvert.ToString(drLOB["RE_RAE_ServiceAccountNo"]);
                    ar.languageCode = TypeConvert.ToString(drLOB["RE_RAE_LanguageCode"]);
                    ar.userTimeZone = TypeConvert.ToString(drLOB["RE_RAE_UserTimeZone"]);                   

                    AppleCare.authenticateResponseType response = appleCareService.Authenticate(ar);

                    m_appleCareUserSessionId = response.userSessionId;
                    m_appleCareUserOperationId = response.operationId;

                    AppleCareSessionDateTime = currentTime;
                }
            }
            catch (Exception exc)
            {
                
            }
        }

        #endregion

        #endregion
    }
}
